// Package crons
// @Link  https://github.com/bufanyun/hotgo
// @Copyright  Copyright (c) 2023 HotGo CLI
// @Author  Ms <133814250@qq.com>
// @License  https://github.com/bufanyun/hotgo/blob/master/LICENSE
package crons

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gogf/gf/v2/os/gtime"
	"hotgo/internal/library/cron"
	"hotgo/internal/model/entity"
	"hotgo/internal/model/input/sysin"
	"hotgo/internal/service"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

func init() {
	cron.Register(SoptEM)
}

// SoptEM 测试任务（无参数）
var SoptEM = &cSoptEM{name: "spot_em"}
var stockZhASpotEm = "http://127.0.0.1:8000/api/public/stock_zh_a_spot_em"
var stockZhASpotIntFlow = "http://127.0.0.1:8000/api/public/stock_fund_flow_individual?symbol="

type stockZhASpotFundFlowResp struct {
	Code      int    `json:"股票代码"`
	Inflow    string `json:"流入资金"`
	Outflow   string `json:"流出资金"`
	NetInflow string `json:"净额"`
}

type stockZhASpotEmResp struct {
	Code                 string  `json:"代码"                 `
	Name                 string  `json:"名称"                 `
	LastPrice            float64 `json:"最新价"            `
	ChangePercent        float64 `json:"涨跌幅"        `
	ChangeAmount         float64 `json:"涨跌额"         `
	Volume               float64 `json:"成交量"               `
	Turnover             float64 `json:"成交额"             `
	Amplitude            float64 `json:"振幅"            `
	High                 float64 `json:"最高"                 `
	Low                  float64 `json:"最低"                  `
	Open                 float64 `json:"今开"                 `
	Closed               float64 `json:"昨收"               `
	VolumeRatio          float64 `json:"量比"          `
	TurnoverRate         float64 `json:"换手率"         `
	PeRatio              float64 `json:"市盈率-动态"              `
	PbRatio              float64 `json:"市净率"              `
	MarketCap            float64 `json:"总市值"            `
	CirculatingMarketCap float64 `json:"流通市值" `
	RiseSpeed            float64 `json:"涨速"            `
	Change5Min           float64 `json:"5分钟涨跌"           `
	ChangeErcent60Day    float64 `json:"60日涨跌幅"    `
	YtdChangePercent     float64 `json:"年初至今涨跌幅"     `
}

type cSoptEM struct {
	name string
}

func (c *cSoptEM) GetName() string {
	return c.name
}

// Execute 执行任务
func (c *cSoptEM) Execute(ctx context.Context, parser *cron.Parser) (err error) {

	response, err := http.Get(stockZhASpotEm)
	if err != nil {
		parser.Logger.Warning(ctx, "cron CloseOrder Execute http.Get err:%+v", err)
		return
	}
	defer response.Body.Close()
	body, err := io.ReadAll(response.Body)
	if err != nil {
		parser.Logger.Warning(ctx, "cron CloseOrder Execute io.ReadAll err:%+v", err)
		return err
	}
	var resp []stockZhASpotEmResp
	err = json.Unmarshal(body, &resp)
	if err != nil {
		parser.Logger.Warning(ctx, "cron CloseOrder Execute json.Unmarshal err:%+v", err)
		return err
	}
	foundFlowData, err := getFoundFlowData(ctx, parser)
	for _, emResp := range resp {
		if emResp.LastPrice == 0 {
			continue
		}
		flowResp, ok := foundFlowData[emResp.Code]
		inflow := float64(0)
		outflow := float64(0)
		netInflow := float64(0)
		if ok {
			inflow = parseFloat(flowResp.Inflow)
			outflow = parseFloat(flowResp.Outflow)
			netInflow = parseFloat(flowResp.NetInflow)
		} else {
			parser.Logger.Warning(ctx, "code, not found inflow", err)

		}
		err := service.SysStockZhASpotEm().Edit(ctx, &sysin.StockZhASpotEmEditInp{
			StockZhASpotEm: entity.StockZhASpotEm{
				Code:                 emResp.Code,
				Name:                 emResp.Name,
				LastPrice:            emResp.LastPrice,
				ChangePercent:        emResp.ChangePercent,
				ChangeAmount:         emResp.ChangeAmount,
				Volume:               emResp.Volume,
				Turnover:             emResp.Turnover,
				Amplitude:            emResp.Amplitude,
				High:                 emResp.High,
				Low:                  emResp.Low,
				Open:                 emResp.Open,
				Closed:               emResp.Closed,
				VolumeRatio:          emResp.VolumeRatio,
				TurnoverRate:         emResp.TurnoverRate,
				PeRatio:              emResp.PeRatio,
				PbRatio:              emResp.PbRatio,
				MarketCap:            emResp.MarketCap,
				CirculatingMarketCap: emResp.CirculatingMarketCap,
				RiseSpeed:            emResp.RiseSpeed,
				Change5Min:           emResp.Change5Min,
				ChangeErcent60Day:    emResp.ChangeErcent60Day,
				YtdChangePercent:     emResp.YtdChangePercent,
				Inflow:               inflow,
				Outflow:              outflow,
				NetInflow:            netInflow,
				Date:                 gtime.Now().Format("Y-m-d"),
			},
		})
		if err != nil {
			parser.Logger.Warning(ctx, "cron CloseOrder Execute service.SysStockZhASpotEm().Edit err:%+v", err)
			continue
		}
	}

	return
}

func getFoundFlowData(ctx context.Context, parser *cron.Parser) (stockFundFlowData map[string]stockZhASpotFundFlowResp, err error) {
	stockFundFlowData = make(map[string]stockZhASpotFundFlowResp)
	response, err := http.Get(fmt.Sprintf("%s%s", stockZhASpotIntFlow, url.QueryEscape("即时")))
	if err != nil {
		parser.Logger.Warning(ctx, "cron CloseOrder Execute http.Get err:%+v", err)
		return stockFundFlowData, err
	}
	defer response.Body.Close()
	body, err := io.ReadAll(response.Body)
	if err != nil {
		parser.Logger.Warning(ctx, "cron CloseOrder Execute io.ReadAll err:%+v", err)
		return stockFundFlowData, err
	}
	var resp []stockZhASpotFundFlowResp
	err = json.Unmarshal(body, &resp)
	if err != nil {
		parser.Logger.Warning(ctx, "cron CloseOrder Execute json.Unmarshal err:%+v", err)
		return stockFundFlowData, err
	}
	for _, flowResp := range resp {
		code := fmt.Sprintf("%06d", flowResp.Code)
		stockFundFlowData[code] = flowResp
	}
	return stockFundFlowData, nil
}

func parseFloat(content string) float64 {
	if strings.Contains(content, "亿") {
		content = strings.TrimRight(content, "亿")
		v, _ := strconv.ParseFloat(content, 64)
		return v * 10000 * 10000
	} else if strings.Contains(content, "万") {
		content = strings.TrimRight(content, "万")
		v, _ := strconv.ParseFloat(content, 64)
		return v * 10000
	} else {
		v, _ := strconv.ParseFloat(content, 64)
		return v
	}
}
